<template>
    <Transition name="zx-zoom-in-top" @after-leave="$emit('dodestroy')">
        <div
            v-show="visible"
            class="zx-picker-panel zx-date-range-picker zx-popper"
            :class="[{
                'has-sidebar': $slots.sidebar || shortcuts
            }, popperClass]"
        >
            <div class="zx-picker-panel__body-wrapper">
                <slot name="sidebar" class="zx-picker-panel__sidebar" />
                <div v-if="shortcuts" class="zx-picker-panel__sidebar">
                    <button
                        v-for="(shortcut, key) in shortcuts"
                        :key="key"
                        type="button"
                        class="zx-picker-panel__shortcut"
                        @click="handleShortcutClick(shortcut)"
                    >
                        {{ shortcut.text }}
                    </button>
                </div>
                <div class="zx-picker-panel__body">
                    <div class="zx-picker-panel__content zx-date-range-picker__content is-left">
                        <div class="zx-date-range-picker__header">
                            <button
                                type="button"
                                class="zx-picker-panel__icon-btn zx-icon-arrow-double-left"
                                @click="leftPrevYear"
                            />
                            <!-- <button
                                v-if="unlinkPanels"
                                type="button"
                                :disabled="!enableYearArrow"
                                :class="{ 'is-disabled': !enableYearArrow }"
                                class="zx-picker-panel__icon-btn zx-icon-arrow-double-right"
                                @click="leftNextYear"
                            /> -->
                            <div>{{ leftLabel }}</div>
                        </div>
                        <MonthTable
                            selection-mode="range"
                            :date="leftDate"
                            :default-value="defaultValue"
                            :min-date="minDate"
                            :max-date="maxDate"
                            :range-state="rangeState"
                            :disabled-date="disabledDate"
                            @changerange="handleChangeRange"
                            @pick="handleRangePick"
                        />
                    </div>
                    <div class="zx-picker-panel__content zx-date-range-picker__content is-right">
                        <div class="zx-date-range-picker__header">
                            <div>{{ rightLabel }}</div>
                            <!-- <button
                                v-if="unlinkPanels"
                                type="button"
                                :disabled="!enableYearArrow"
                                :class="{ 'is-disabled': !enableYearArrow }"
                                class="zx-picker-panel__icon-btn zx-icon-arrow-double-left"
                                @click="rightPrevYear"
                            /> -->
                            <button
                                type="button"
                                class="zx-picker-panel__icon-btn zx-icon-arrow-double-right"
                                @click="rightNextYear"
                            />
                        </div>
                        <MonthTable
                            selection-mode="range"
                            :date="rightDate"
                            :default-value="defaultValue"
                            :min-date="minDate"
                            :max-date="maxDate"
                            :range-state="rangeState"
                            :disabled-date="disabledDate"
                            @changerange="handleChangeRange"
                            @pick="handleRangePick"
                        />
                    </div>
                </div>
            </div>
        </div>
    </Transition>
</template>

<script type="text/babel">
import {
    isDate,
    modifyWithTimeString,
    prevYear,
    nextYear,
    nextMonth,
} from '@src/utils/date-util';
import Clickoutside from '@src/utils/clickoutside';
import Locale from '@src/mixins/locale';
import MonthTable from '../basic/month-table';
import ZxInput from '../../../../components/input';
import ZxButton from '../../../../components/button';

const calcDefaultValue = (defaultValue) => {
    if (Array.isArray(defaultValue)) {
        return [new Date(defaultValue[0]), new Date(defaultValue[1])];
    } else if (defaultValue) {
        return [new Date(defaultValue), nextMonth(new Date(defaultValue))];
    } else {
        return [new Date(), nextMonth(new Date())];
    }
};
export default {

    directives: { Clickoutside },

    components: {
        MonthTable,
        ZxInput,
        ZxButton,
    },
    mixins: [Locale],

    data() {
        return {
            popperClass: '',
            value: [],
            defaultValue: null,
            defaultTime: null,
            minDate: '',
            maxDate: '',
            leftDate: new Date(),
            rightDate: nextYear(new Date()),
            rangeState: {
                endDate: null,
                selecting: false,
                row: null,
                column: null,
            },
            shortcuts: '',
            visible: '',
            disabledDate: '',
            format: '',
            arrowControl: false,
            unlinkPanels: false,
        };
    },

    computed: {
        btnDisabled() {
            return !(this.minDate && this.maxDate && !this.selecting && this.isValidValue([this.minDate, this.maxDate]));
        },

        leftLabel() {
            return this.leftDate.getFullYear() + ' ' + this.t('el.datepicker.year');
        },

        rightLabel() {
            return this.rightDate.getFullYear() + ' ' + this.t('el.datepicker.year');
        },

        leftYear() {
            return this.leftDate.getFullYear();
        },

        rightYear() {
            return this.rightDate.getFullYear() === this.leftDate.getFullYear() ? this.leftDate.getFullYear() + 1 : this.rightDate.getFullYear();
        },

        enableYearArrow() {
            return this.unlinkPanels && this.rightYear > this.leftYear + 1;
        },
    },

    watch: {
        value(newVal) {
            if (!newVal) {
                this.minDate = null;
                this.maxDate = null;
            } else if (Array.isArray(newVal)) {
                this.minDate = isDate(newVal[0]) ? new Date(newVal[0]) : null;
                this.maxDate = isDate(newVal[1]) ? new Date(newVal[1]) : null;
                if (this.minDate) {
                    this.leftDate = this.minDate;
                    if (this.unlinkPanels && this.maxDate) {
                        const minDateYear = this.minDate.getFullYear();
                        const maxDateYear = this.maxDate.getFullYear();
                        this.rightDate = minDateYear === maxDateYear
                            ? nextYear(this.maxDate)
                            : this.maxDate;
                    } else {
                        this.rightDate = nextYear(this.leftDate);
                    }
                } else {
                    this.leftDate = calcDefaultValue(this.defaultValue)[0];
                    this.rightDate = nextYear(this.leftDate);
                }
            }
        },

        defaultValue(val) {
            if (!Array.isArray(this.value)) {
                const [left, right] = calcDefaultValue(val);
                this.leftDate = left;
                this.rightDate = val && val[1] && left.getFullYear() !== right.getFullYear() && this.unlinkPanels
                    ? right
                    : nextYear(this.leftDate);
            }
        },
    },

    methods: {
        handleClear() {
            this.minDate = null;
            this.maxDate = null;
            this.leftDate = calcDefaultValue(this.defaultValue)[0];
            this.rightDate = nextYear(this.leftDate);
            this.$emit('pick', null);
        },

        handleChangeRange(val) {
            this.minDate = val.minDate;
            this.maxDate = val.maxDate;
            this.rangeState = val.rangeState;
        },

        handleRangePick(val, close = true) {
            const defaultTime = this.defaultTime || [];
            const minDate = modifyWithTimeString(val.minDate, defaultTime[0]);
            const maxDate = modifyWithTimeString(val.maxDate, defaultTime[1]);
            if (this.maxDate === maxDate && this.minDate === minDate) {
                return;
            }
            this.onPick && this.onPick(val);
            this.maxDate = maxDate;
            this.minDate = minDate;

            setTimeout(() => {
                this.maxDate = maxDate;
                this.minDate = minDate;
            }, 10);
            if (!close) return;
            this.handleConfirm();
        },

        handleShortcutClick(shortcut) {
            if (shortcut.onClick) {
                shortcut.onClick(this);
            }
        },

        // leftPrev*, rightNext* need to take care of `unlinkPanels`
        leftPrevYear() {
            this.leftDate = prevYear(this.leftDate);
            if (!this.unlinkPanels) {
                this.rightDate = prevYear(this.rightDate);
            }
        },

        rightNextYear() {
            if (!this.unlinkPanels) {
                this.leftDate = nextYear(this.leftDate);
            }
            this.rightDate = nextYear(this.rightDate);
        },

        // leftNext*, rightPrev* are called when `unlinkPanels` is true
        leftNextYear() {
            this.leftDate = nextYear(this.leftDate);
        },

        rightPrevYear() {
            this.rightDate = prevYear(this.rightDate);
        },

        handleConfirm(visible = false) {
            if (this.isValidValue([this.minDate, this.maxDate])) {
                this.$emit('pick', [this.minDate, this.maxDate], visible);
            }
        },

        isValidValue(value) {
            return Array.isArray(value) &&
                value && value[0] && value[1] &&
                isDate(value[0]) && isDate(value[1]) &&
                value[0].getTime() <= value[1].getTime() && (
                typeof this.disabledDate === 'function'
                    ? !this.disabledDate(value[0]) && !this.disabledDate(value[1])
                    : true
            );
        },

        resetView() {
            // NOTE: this is a hack to reset {min, max}Date on picker open.
            // TODO: correct way of doing so is to refactor {min, max}Date to be dependent on value and internal selection state
            //       an alternative would be resetView whenever picker becomes visible, should also investigate date-panel's resetView
            this.minDate = this.value && isDate(this.value[0]) ? new Date(this.value[0]) : null;
            this.maxDate = this.value && isDate(this.value[0]) ? new Date(this.value[1]) : null;
        },
    },
};
</script>
